package com.smsc.headend.task.engine.controller;

import com.smsc.headend.common.enums.DeviceType;
import com.smsc.headend.module.asset.dmo.MeterConfigDMO;
import com.smsc.headend.module.asset.entity.ComEntity;
import com.smsc.headend.module.data.dto.RequestTaskDTO;
import com.smsc.headend.module.data.dto.TaskPacketDTO;
import com.smsc.headend.module.request.MessageTaskDto;
import com.smsc.headend.module.task.dto.ConnectorTaskResult;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.module.task.entity.DeviceTask;
import com.smsc.headend.task.engine.manager.OdrRequestManager;
import com.smsc.headend.task.engine.po.TaskEndStatusPo;
import com.smsc.headend.task.engine.service.FeignAssetManagementService;
import com.smsc.headend.task.engine.service.task.DeviceTaskService;
import com.smsc.headend.task.engine.service.task.TaskDataService;
import com.smsc.headend.task.engine.service.task.TaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author liangli
 * @date 2020/9/7
 */
@RestController
@RequestMapping("task")
@Slf4j
public class RequestTaskController {

    @Autowired
    OdrRequestManager odrRequestManager;
    @Autowired
    TaskDataService taskDataService;

    @Autowired
    DeviceTaskService deviceTaskService;

    @Autowired
    FeignAssetManagementService feignAssetManagementService;

    @Autowired
    TaskService taskService;


    @RequestMapping("execute")
    public Integer executeTask(@RequestBody Task task) {
        log.info("ExecuteTask: comId:{},meterId:{},type:{},no:{}", task.getComId(), task.getMeterId(), task.getTaskType(), task.getTaskNo());

        TaskEndStatusPo taskEndStatusPo = taskService.doStartTask(task);
        if (taskEndStatusPo != null) {
            if (taskEndStatusPo != null) {
                taskService.handleTaskEndPo(taskEndStatusPo, task);
            }
        }
        return 1;
    }


    @RequestMapping("callback")
    Integer responseTask(@RequestBody ConnectorTaskResult connectorTaskResult) {
        log.info("TaskRestResponse:no:{},try get response", connectorTaskResult.getAtomicTaskNo());
        try {
            taskService.atomicTaskResponse(connectorTaskResult);
        } catch (IllegalAccessException | InstantiationException e) {
            log.error("Request CallBack TaskError, taskNo:{}", connectorTaskResult.getAtomicTaskNo(), e);
        }
        return 1;
    }

    @RequestMapping("processing")
    public RequestTaskDTO taskProcessingInfo(@RequestParam String messageId) {
        List<DeviceTask> tasks = odrRequestManager.getDeviceTask(messageId);
        if (CollectionUtils.isEmpty(tasks)) {
            Long time = taskDataService.getMessageIdTime(messageId);
            if (time != null) {
                taskDataService.setMessageIdTime(messageId);
                return taskDataService.emptyProcessingResult();
            }
        }
        taskDataService.setMessageIdTime(messageId);
        return CollectionUtils.isEmpty(tasks) ? null : taskDataService.getTaskProcessingResult(tasks, messageId);
    }

    @RequestMapping("request/detail")
    public MessageTaskDto getOdrRequestMessageContent(@RequestParam String messageId) {
        taskDataService.setMessageIdTime(messageId);
        return odrRequestManager.getMessageDto(messageId);
    }


    @RequestMapping("packet")
    public List<TaskPacketDTO> requestPacket(@RequestParam String messageId) {
        List<DeviceTask> tasks = odrRequestManager.getDeviceTask(messageId);
        log.info("query message:{}, taskSize:{}", messageId, CollectionUtils.isEmpty(tasks) ? 0 : tasks.size());
        return taskDataService.getTaskPacket(tasks);
    }

    @RequestMapping("packet/analyse")
    public List<TaskPacketDTO> analysePacket(@RequestBody List<TaskPacketDTO> dto) {
        if (dto == null) {
            return null;
        }
        return dto.stream().map(taskDataService::analysePacket).collect(Collectors.toList());
    }

    @RequestMapping("packetByTaskNo")
    public List<TaskPacketDTO> packetByTaskNo(@RequestParam String taskNo) {
        return taskDataService.getTaskPacketByTaskNo(taskNo);
    }

    @RequestMapping("deviceTaskEstimate")
    public String deviceTaskEstimate(Long deviceType, Long deviceId) {
        Long comId = null;
        Long taskDeviceId = deviceId;
        if (deviceType.equals(DeviceType.METER.getId())) {
//            Meter meter = assetService.getMeterById(deviceId);
            MeterConfigDMO meterConfigById = feignAssetManagementService.getMeterConfigById(deviceId);
            if (meterConfigById == null) {
                return "-1";
            }
            comId = meterConfigById.getComId();
            taskDeviceId = deviceId;
        } else if (deviceType.equals(DeviceType.DCU.getId())) {
            ComEntity comByDeviceId = feignAssetManagementService.getComByDeviceId(deviceId);
            if (comByDeviceId == null) {
                return "-1";
            }
            comId = comByDeviceId.getComId();
            taskDeviceId = -1L;
        }
        return deviceTaskService.estimateSingleDeviceTaskTime(comId, taskDeviceId);
    }


    /**
     * 获取任务的状态与开始结束时间
     *
     * @param taskNos
     * @return
     */
    @RequestMapping("detail/taskNo")
    public List<DeviceTask> getDeviceTasksByTaskNo(@RequestParam("taskNos") List<String> taskNos) {
        if (CollectionUtils.isEmpty(taskNos)) {
            log.error("getDeviceTasksByTaskNo with empty taskNos");
            return null;
        }

        if (taskNos.size() > 100) {
            log.error("query task status size over limit");
            return null;
        }
        return taskDataService.getDeviceTaskTvAndStatus(taskNos);
    }
}
